/* 
 * File:   Network.h
 * Author: André
 *
 * Created on November 30, 2012, 9:09 PM
 */

#ifndef NETWORK_H
#define	NETWORK_H

#include "Neuron.h"
#include "Connection.h"
#include "DataSet.h"

class Network {
    
public:
    Network(DataSet* data);                                                     //constructor (if k>1, k-hold cross validation)
    virtual ~Network();                                                         // destructor 2B implemented       
    
    int totalNumberOfLayers();                                                  // returns total number of layers including input and output
    int numberOfConnections();                                                  // returns total number of SETS of connections (layers-1)
    
    double runNetwork();                                                        // unique function for handling both regular computation AND k-fold cross validation
   
   
private:
    DataSet* data;                                                              // DataSet object
    
    int numberOfInputNeurons;                                                   // stores number of input neurons (input values)
    int numberOfOutputNeurons;                                                  // stores number of output neurons (output values)
    int numberOfHiddenLayers;                                                   // stores number of hidden layers (user specified)
    int* numberOfNeuronsPerHiddenLayer;                                         // array containing number of neurons per hidden layer
    
    double learningRate;                                                        // neural net learning rate (tweaking parameter)
    double errorTolerance;                                                      // minimum AVERAGE error desired in computation
    
    Neuron* inputNeuronArray;                                                   // holds information on input neuron values
    Neuron* outputNeuronArray;                                                  // holds information on output neuron values
    Neuron** hiddenNeuronArray;                                                 // holds information on hidden neuron values
    Neuron* biasNeuron;                                                         // holds the bias neuron
    
    Connection** biasConnections;                                               // connections from the bias neuron to all sets of connections except the input layer   [i][j] i = to layer i, j = neuron index      
    Connection*** connectionArray;                                              // connections from neurons on a previous layer to subsequent layers    [i][j][k] i = outbound layer, j = outbound neuron, k = inbound neuron
    
    void initializeNeurons(int bin, int entry);                                 // initialize neurons with entry and bin specified
    
    void createConnections();                                                   // builds the connection arrays according to number of layers and neurons
    void initializeWeights();                                                   // sets random weights to connections
    double randomWeight();                                                      // generates a random weight value
    
    double sigmoid(double value);                                               // sigmoid/logistic function
    double sigmoidPrime(double value);                                          // first derivative of sigmoid/logistic function
    
    double feedForward(int bin, int entry);                                     // run neural net from left to right to calculate values for hidden layer neurons and output, return value is total error averaged by number of outputs
    
    void backPropagate(int bin, int entry);                                  // deltas and weights performed by layer before moving on to the next
    void backPropagateWithDerivative(int bin, int entry);                       

    void trainNetwork();                                                        // train network in regards to currentValidationSet
    double validateNetwork();                                                   // validate in regards to currentValidationSet

    /****** for usage with k-cross validation ******/
    
    int bins;                                                             // k value for k-cross validation
    int numEntriesPerBin;
    int currentValidationSet;                                                   // validation set being used in the computation
    
};

#endif	/* NETWORK_H */

